package top.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import top.api.Constants.SystemConstants;
import top.api.common.ResponseResult;
import top.api.domain.dto.AddMenuDto;
import top.api.domain.dto.UpdateMenuDto;
import top.api.domain.entity.Menu;
import top.api.domain.entity.Role;
import top.api.domain.entity.RoleMenu;
import top.api.domain.entity.User;
import top.api.domain.vo.MenuListVo;
import top.api.domain.vo.MenuTreeSelectVo;
import top.api.domain.vo.RoutersVo;
import top.api.domain.vo.roleMenuTreeselectVo;
import top.api.enums.AppHttpCodeEnum;
import top.api.mapper.RoleMenuMapper;
import top.api.service.LinkService;
import top.api.service.MenuService;
import top.api.mapper.MenuMapper;
import org.springframework.stereotype.Service;
import top.api.utils.BeanCopyUtils;
import top.api.utils.SecurityUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 27465
* @description 针对表【sys_menu(菜单权限表)】的数据库操作Service实现
* @createDate 2023-02-01 19:22:59
*/
@Service
@Slf4j
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu>
    implements MenuService{

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    public List<String> selectPerms(User user) {
        // type: 1  管理员返回所有
        if (SecurityUtils.isAdmin()){
            LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
            // 菜单类型（M目录 C菜单 F按钮）菜单类型为C或者F的
            queryWrapper.in(Menu::getMenuType, SystemConstants.MENU,SystemConstants.BUTTON);
            queryWrapper.eq(Menu::getStatus,SystemConstants.STATUS_NORMAL);
            List<Menu> menus = super.list(queryWrapper);
            List<String> perms = new ArrayList<>();
            for (Menu menu : menus) {
                perms.add(menu.getPerms());
            }
            return perms;
        }

        // 查询对应的菜单权限信息
        List<String> perms = menuMapper.selectPermsByUserId(user.getId());

        return perms;
    }

    @Override
    public List<Menu> selectRouterMenuTree(User user) {
        List<Menu> menus = null;
        //判断是否是管理员
        if(SecurityUtils.isAdmin()){
            //如果是 获取所有符合要求的Menu
            menus = menuMapper.selectAllRouterMenu();
        }else{
            //否则  获取当前用户所具有的Menu
            menus = menuMapper.selectRouterMenuTreeByUserId(user.getId());
        }

        //构建tree
        //先找出第一层的菜单  然后去找他们的子菜单设置到children属性中
        List<Menu> menuTree = builderMenuTree(menus,0L);

        return menuTree;
    }

    @Override
    public ResponseResult getMenuListByMenuNameAndStatus(String menuName, String status) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(menuName),Menu::getMenuName,menuName);
        queryWrapper.eq(StringUtils.hasText(status),Menu::getStatus,status);

        List<Menu> menus = menuMapper.selectList(queryWrapper);

        List<MenuListVo> menuListVos = BeanCopyUtils.copyBeanList(menus, MenuListVo.class);

        return ResponseResult.okResult(menuListVos);
    }

    @Override
    public ResponseResult addMenu(AddMenuDto addMenuDto) {
        Menu menu = BeanCopyUtils.copyBean(addMenuDto, Menu.class);
        menuMapper.insert(menu);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getMenuInfo(Long id) {
        Menu menu = menuMapper.selectById(id);
        MenuListVo menuListVo = BeanCopyUtils.copyBean(menu, MenuListVo.class);
        return ResponseResult.okResult(menuListVo);
    }

    @Override
    public ResponseResult updateMenu(UpdateMenuDto updateMenuDto) {
        if (! ObjectUtils.isEmpty(updateMenuDto.getParentId()) && updateMenuDto.getParentId().equals(updateMenuDto.getId())){
            return ResponseResult.errorResult(AppHttpCodeEnum.UPDATE_MENU_ERR);
        }

        Menu menu = BeanCopyUtils.copyBean(updateMenuDto, Menu.class);

        menuMapper.updateById(menu);

        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult deleteMenu(Long id) {
        // 查询该菜单是否有子菜单
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getParentId,id);
        Integer count = menuMapper.selectCount(queryWrapper);
        if (count > 0){
            return ResponseResult.errorResult(AppHttpCodeEnum.DELETE_MENU_ERR);
        }

        // 伪删除
        LambdaUpdateWrapper<Menu> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Menu::getId,id);
        updateWrapper.set(Menu::getDelFlag,SystemConstants.DelFlagNO);

        super.update(updateWrapper);

        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult treeSelect() {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getStatus,SystemConstants.STATUS_MENU_OK);

        List<Menu> menus = menuMapper.selectList(queryWrapper);
        // 数据拷贝
        List<MenuTreeSelectVo> menuTreeSelectVoList = new ArrayList<>();
        for (Menu menu : menus) {
            menuTreeSelectVoList.add(new MenuTreeSelectVo(null,menu.getId(),menu.getMenuName(),menu.getParentId()));
        }

        //构建tree
        //先找出第一层的菜单  然后去找他们的子菜单设置到children属性中
        List<MenuTreeSelectVo> menuTreeSelectVos = builderMenuTreeSelectVo(menuTreeSelectVoList, 0L);

        //封装数据返回
        return ResponseResult.okResult(menuTreeSelectVos);
    }

    @Override
    public ResponseResult roleMenuTreeselect(Long id) {
        // 找出所有的菜单tree
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getStatus,SystemConstants.STATUS_MENU_OK);

        List<Menu> menus = menuMapper.selectList(queryWrapper);
        // 数据拷贝
        List<MenuTreeSelectVo> menuTreeSelectVoList = new ArrayList<>();
        for (Menu menu : menus) {
            menuTreeSelectVoList.add(new MenuTreeSelectVo(null,menu.getId(),menu.getMenuName(),menu.getParentId()));
        }

        List<MenuTreeSelectVo> menuTreeSelectVos = builderMenuTreeSelectVo(menuTreeSelectVoList, 0L);

        // 找出自己拥有的菜单
        LambdaQueryWrapper<RoleMenu> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(RoleMenu::getRoleId,id);
        List<RoleMenu> roleMenus = roleMenuMapper.selectList(queryWrapper1);

        // 封装vo
        roleMenuTreeselectVo roleMenuTreeselectVo = new roleMenuTreeselectVo();
        List<String> keys = new ArrayList<>();
        for (RoleMenu roleMenu : roleMenus) {
            keys.add(roleMenu.getMenuId().toString());
        }
        roleMenuTreeselectVo.setCheckedKeys(keys);
        roleMenuTreeselectVo.setMenus(menuTreeSelectVos);

        return ResponseResult.okResult(roleMenuTreeselectVo);
    }

    private List<MenuTreeSelectVo> builderMenuTreeSelectVo(List<MenuTreeSelectVo> MenuTreeSelectVo, Long parentId) {
        // 获取根菜单
        List<MenuTreeSelectVo> menuTreeSelectVoList = MenuTreeSelectVo.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .collect(Collectors.toList());

        for (MenuTreeSelectVo menuTreeSelectVo : menuTreeSelectVoList) {
            menuTreeSelectVo.setChildren(getMenuTreeSelectVoChildren(menuTreeSelectVo,MenuTreeSelectVo));
        }

        return menuTreeSelectVoList;
    }
    private List<MenuTreeSelectVo> getMenuTreeSelectVoChildren(MenuTreeSelectVo menuTreeSelectVo, List<MenuTreeSelectVo> menuTreeSelectVoList) {
        // 把对应的子菜单全部找出来
        List<MenuTreeSelectVo> collect = menuTreeSelectVoList.stream()
                .filter(m -> m.getParentId().equals(menuTreeSelectVo.getId()))
                .collect(Collectors.toList());

        for (MenuTreeSelectVo treeSelectVo : collect) {
            treeSelectVo.setChildren(getMenuTreeSelectVoChildren(treeSelectVo,menuTreeSelectVoList));
        }

        return collect;
    }







    private List<Menu> builderMenuTree(List<Menu> menus, Long parentId) {
        List<Menu> menuTree = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> menu.setChildren(getChildren(menu, menus)))
                .collect(Collectors.toList());
        return menuTree;
    }

    /**
     * 获取存入参数的 子Menu集合
     * @param menu
     * @param menus
     * @return
     */
    private List<Menu> getChildren(Menu menu, List<Menu> menus) {
        List<Menu> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                .map(m -> m.setChildren(getChildren(m, menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
}




